#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
WebDAV XML响应构建器

构建WebDAV协议所需的XML响应，包括PROPFIND、错误响应等
"""

import xml.etree.ElementTree as ET
from typing import List, Dict, Any, Optional
from datetime import datetime


class WebDAVXMLBuilder:
    """WebDAV XML响应构建器"""
    
    def __init__(self):
        # WebDAV命名空间
        self.dav_ns = "DAV:"
        self.dav_prefix = "{DAV:}"
    
    def build_propfind_response(self, files: List[Dict[str, Any]], base_url: str, depth: int = 1) -> str:
        """
        构建PROPFIND XML响应
        
        Args:
            files: 文件/目录信息列表
            base_url: 基础URL
            depth: 查询深度 (0, 1, infinity)
        
        Returns:
            XML字符串
        """
        multistatus = ET.Element(f"{self.dav_prefix}multistatus")
        
        for file_info in files:
            response = ET.SubElement(multistatus, f"{self.dav_prefix}response")
            
            # href元素
            href = ET.SubElement(response, f"{self.dav_prefix}href")
            file_path = file_info.get('path', file_info.get('name', ''))
            if file_path and file_path != '/':
                # 移除开头的斜杠并添加到base_url
                clean_path = file_path.lstrip('/')
                href.text = f"{base_url.rstrip('/')}/{clean_path}"
            else:
                href.text = base_url
            
            # propstat元素
            propstat = ET.SubElement(response, f"{self.dav_prefix}propstat")
            
            # prop元素
            prop = ET.SubElement(propstat, f"{self.dav_prefix}prop")
            
            # 添加文件属性
            self._add_file_properties(prop, file_info)
            
            # status元素
            status = ET.SubElement(propstat, f"{self.dav_prefix}status")
            status.text = "HTTP/1.1 200 OK"
        
        return ET.tostring(multistatus, encoding='utf-8', xml_declaration=True)
    
    def _add_file_properties(self, prop: ET.Element, file_info: Dict[str, Any]):
        """添加文件属性到prop元素"""
        
        # creationdate
        creationdate = ET.SubElement(prop, f"{self.dav_prefix}creationdate")
        creationdate.text = file_info.get('created_at', datetime.utcnow().isoformat() + 'Z')
        
        # getlastmodified
        getlastmodified = ET.SubElement(prop, f"{self.dav_prefix}getlastmodified")
        last_modified = file_info.get('modified_at', datetime.utcnow())
        if isinstance(last_modified, str):
            getlastmodified.text = last_modified
        elif isinstance(last_modified, datetime):
            getlastmodified.text = last_modified.strftime('%a, %d %b %Y %H:%M:%S GMT')
        else:
            getlastmodified.text = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
        
        # getcontentlength
        if not file_info.get('is_directory', False):
            getcontentlength = ET.SubElement(prop, f"{self.dav_prefix}getcontentlength")
            getcontentlength.text = str(file_info.get('size', 0))
        
        # getcontenttype
        getcontenttype = ET.SubElement(prop, f"{self.dav_prefix}getcontenttype")
        if file_info.get('is_directory', False):
            getcontenttype.text = "httpd/unix-directory"
        else:
            getcontenttype.text = file_info.get('content_type', 'application/octet-stream')
        
        # getetag
        getetag = ET.SubElement(prop, f"{self.dav_prefix}getetag")
        getetag.text = f'"{file_info.get("etag", "unknown")}"'
        
        # resourcetype
        resourcetype = ET.SubElement(prop, f"{self.dav_prefix}resourcetype")
        if file_info.get('is_directory', False):
            ET.SubElement(resourcetype, f"{self.dav_prefix}collection")
        
        # displayname
        displayname = ET.SubElement(prop, f"{self.dav_prefix}displayname")
        displayname.text = file_info.get('name', '')
    
    def build_error_response(self, error_code: int, error_message: str) -> str:
        """
        构建错误响应XML
        
        Args:
            error_code: HTTP错误码
            error_message: 错误消息
        
        Returns:
            XML字符串
        """
        multistatus = ET.Element(f"{self.dav_prefix}multistatus")
        
        response = ET.SubElement(multistatus, f"{self.dav_prefix}response")
        
        # href元素
        href = ET.SubElement(response, f"{self.dav_prefix}href")
        href.text = "/"  # 默认路径
        
        # propstat元素
        propstat = ET.SubElement(response, f"{self.dav_prefix}propstat")
        
        # prop元素（空）
        ET.SubElement(propstat, f"{self.dav_prefix}prop")
        
        # status元素
        status = ET.SubElement(propstat, f"{self.dav_prefix}status")
        status.text = f"HTTP/1.1 {error_code} {error_message}"
        
        return ET.tostring(multistatus, encoding='utf-8', xml_declaration=True)
    
    def build_empty_propfind_response(self, base_url: str) -> str:
        """
        构建空的PROPFIND响应（用于不存在的资源）
        
        Args:
            base_url: 基础URL
        
        Returns:
            XML字符串
        """
        multistatus = ET.Element(f"{self.dav_prefix}multistatus")
        
        response = ET.SubElement(multistatus, f"{self.dav_prefix}response")
        
        # href元素
        href = ET.SubElement(response, f"{self.dav_prefix}href")
        href.text = base_url
        
        # propstat元素
        propstat = ET.SubElement(response, f"{self.dav_prefix}propstat")
        
        # prop元素（空）
        ET.SubElement(propstat, f"{self.dav_prefix}prop")
        
        # status元素
        status = ET.SubElement(propstat, f"{self.dav_prefix}status")
        status.text = "HTTP/1.1 404 Not Found"
        
        return ET.tostring(multistatus, encoding='utf-8', xml_declaration=True)
    
    def build_move_response(self, source_url: str, destination_url: str) -> str:
        """
        构建MOVE操作响应
        
        Args:
            source_url: 源URL
            destination_url: 目标URL
        
        Returns:
            XML字符串
        """
        multistatus = ET.Element(f"{self.dav_prefix}multistatus")
        
        response = ET.SubElement(multistatus, f"{self.dav_prefix}response")
        
        # href元素
        href = ET.SubElement(response, f"{self.dav_prefix}href")
        href.text = source_url
        
        # propstat元素
        propstat = ET.SubElement(response, f"{self.dav_prefix}propstat")
        
        # prop元素（空）
        ET.SubElement(propstat, f"{self.dav_prefix}prop")
        
        # status元素
        status = ET.SubElement(propstat, f"{self.dav_prefix}status")
        status.text = "HTTP/1.1 201 Created"
        
        return ET.tostring(multistatus, encoding='utf-8', xml_declaration=True)
    
    def build_copy_response(self, source_url: str, destination_url: str) -> str:
        """
        构建COPY操作响应
        
        Args:
            source_url: 源URL
            destination_url: 目标URL
        
        Returns:
            XML字符串
        """
        multistatus = ET.Element(f"{self.dav_prefix}multistatus")
        
        response = ET.SubElement(multistatus, f"{self.dav_prefix}response")
        
        # href元素
        href = ET.SubElement(response, f"{self.dav_prefix}href")
        href.text = source_url
        
        # propstat元素
        propstat = ET.SubElement(response, f"{self.dav_prefix}propstat")
        
        # prop元素（空）
        ET.SubElement(propstat, f"{self.dav_prefix}prop")
        
        # status元素
        status = ET.SubElement(propstat, f"{self.dav_prefix}status")
        status.text = "HTTP/1.1 201 Created"
        
        return ET.tostring(multistatus, encoding='utf-8', xml_declaration=True)


# 全局实例
xml_builder = WebDAVXMLBuilder()
